﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CopySniffer.Common;
using System.Runtime.Serialization;

namespace CopySniffer.Search
{
    [Serializable]
    [DataContract]
    public sealed class SearchInfo : IEquatable<SearchInfo>
    {
        public SearchInfo()
        {
        }

        public SearchInfo(string tokenContents)
            : this(new SearchToken(tokenContents))
        {
        }

        public SearchInfo(string tokenContents, bool exactMatch)
            : this(new SearchToken(tokenContents, exactMatch))
        {
        }

        public SearchInfo(string tokenContents, bool exactMatch, bool negated)
            : this(new SearchToken(tokenContents, exactMatch, negated))
        {
        }

        public SearchInfo(SearchToken token)
            : this()
        {
            Tokens.Add(token);
        }

        public SearchInfo(IEnumerable<string> tokenContents)
            : this()
        {
            tokens = tokenContents.ToList<SearchToken, string>(s => new SearchToken(s));
        }


        private List<SearchToken> tokens;

        [DataMember]
        public IList<SearchToken> Tokens 
        {
            get 
            {
                if (tokens == null)
                {
                    tokens = new List<SearchToken>();
                }
                return tokens; 
            }

            private set { tokens = value.ToList(); }
        }

        public static IEnumerable<SearchInfo> GetSearchInfos(IEnumerable<string> tokenContents)
        {
            return tokenContents.ToList<SearchInfo, string>(s => new SearchInfo(s));
        }

        public static IEnumerable<SearchInfo> GetSearchInfos(IEnumerable<string> tokenContents, bool exactMatch)
        {
            return tokenContents.ToList<SearchInfo, string>(s => new SearchInfo(s, exactMatch));
        }

        public static IEnumerable<SearchInfo> GetSearchInfos(IEnumerable<string> tokenContents, bool exactMatch, bool negated)
        {
            return tokenContents.ToList<SearchInfo, string>(s => new SearchInfo(s, exactMatch, negated));
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            Tokens.ForEach(t => sb.AppendFormat("{0} ", t));
            sb.Remove(sb.Length - 1, 1);
            return sb.ToString();
        }

        public override bool Equals(object obj)
        {
            SearchInfo other = obj as SearchInfo;
            if (other != null)
            {
                return Equals(other);
            }
            return false;
        }

        public override int GetHashCode()
        {
            return ToString().GetHashCode();
        }

        #region IEquatable<SearchInfo> Members

        public bool Equals(SearchInfo other)
        {
            if (other == null)
            {
                return false;
            }
            else if (Object.ReferenceEquals(this, other))
            {
                return true;
            }
            else
            {
                return other.ToString().Equals(
                    this.ToString(),
                    StringComparison.InvariantCultureIgnoreCase);
            }
        }

        #endregion
    }
}
